package marketplace.jpa.dao;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import marketplace.jpa.datas.DataAdministrador;
import marketplace.jpa.datas.DataCliente;
import marketplace.jpa.datas.DataContenidoDigital;
import marketplace.jpa.datas.DataProveedor;
import marketplace.jpa.datas.Estado;
import marketplace.jpa.entities.Administrador;
import marketplace.jpa.entities.Cliente;
import marketplace.jpa.entities.ContenidoDigital;
import marketplace.jpa.entities.Proveedor;
import marketplace.jpa.entities.Usuario;
import marketplace.jpa.interfaces.IUsuarioDAO;

@Stateless
public class UsuarioDAO implements IUsuarioDAO {

	@PersistenceContext(unitName="Marketplace")
	EntityManager em;
	
	
	/////////////////////////////////// ADMINISTRADOR ///////////////////////////////////////////
	
	

	
	////////////////////////////////////////////////////////////////////////// GUARDAR ////
	

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean guardarAdministrador(DataAdministrador dataAdministrador) throws Exception {		
		boolean resultado = false;
		Usuario u = new Administrador(dataAdministrador);
		// Persisto el Administrador
		try{
			em.persist(u);			
			em.flush();
			resultado = true;
		}catch(Exception e){
			System.out.println("Error DAO Administrador (Funcion guardarAdministrador): " + e.getMessage());
		}
		return resultado;
	}

	
	////////////////////////////////////////////////////////////////////////// MODIFICAR ////	


	@Override
	public void modificarAdministrador(DataAdministrador da) {
		try{			
			Administrador usr = em.find(Administrador.class, da.getMail());
			
			usr.setNick(da.getNick());
			usr.setNomCompleto(da.getNomCompleto());
			usr.setApellido(da.getApellido());
			usr.setFechaNto(da.getFechaNto());
			usr.setMovil(da.getMovil());
			usr.setSexo(da.getSexo());

			em.persist(usr);
			em.flush();			
		}catch(Exception e){
			System.out.println("Error DAO Administrador (Funcion modificarAdministrador): " + e.getMessage());
		}
	}

	
	////////////////////////////////////////////////////////////////////////// ELIMINAR ////	
	

	@Override
	public void eliminarAdministrador(String mail) {
		try{				
			 Administrador a = em.find(Administrador.class, mail);
			 a.setEstado(Estado.INACTIVO.toString());
			 //em.remove(a);
			 em.persist(a);
			 em.flush();
		} catch(Exception e){
			System.out.println("Error DAO Administrador (Funcion eliminarAdministrador): " + e.getMessage());
		}
	}
	
	
	////////////////////////////////////////////////////////////////////////// EXISTE ////
	

	@Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)		
	public boolean existeAdministrador(String mail) throws Exception {		
		boolean existe = false;
		try{			
			Query q = em.createQuery("select u from Administrador u where u.mail = ?1 and u.estado = ?2");
			q.setParameter(1, mail);
			q.setParameter(2, Estado.ACTIVO.toString());
			if (!q.getSingleResult().equals(null)) existe = true;		
		}catch(Exception e){ System.out.println("Error DAO Administrador (Funcion existeAdministrador): " + e.getMessage()); }				
		return existe;
	}
	
	
	////////////////////////////////////////////////////////////////////////// OBTENER ////
	

	@Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)	
	public DataAdministrador obtenerAdministrador(String mail) throws Exception {
		Usuario u = new Administrador();
		DataAdministrador dub = null;
		try{			
			Query q = em.createQuery("select u from Administrador u where u.mail = ?1 and u.estado = ?2");
			q.setParameter(1, mail);
			q.setParameter(2, Estado.ACTIVO.toString());			
		    u = (Administrador) q.getSingleResult();
		    dub = new DataAdministrador((Administrador) u);
		} 
		catch(Exception e){ System.out.println("Error DAO Administrador (Funcion obtenerAdministrador): " + e.getMessage()); }				
		return dub;
	}

	
	////////////////////////////////////////////////////////////////////////// OBTENER TODOS ////
	

	@Override
	public List<DataAdministrador> getAdministradores() {
		List<DataAdministrador> lstAdministradores = new ArrayList<DataAdministrador>();
		try{		
			Query q = em.createQuery("select u from Administrador u");
			@SuppressWarnings("unchecked")
			List<Administrador> lstAdminsDB = (List<Administrador>) q.getResultList();
			for (Administrador ub : lstAdminsDB) {
				DataAdministrador dub = new DataAdministrador(ub);
				lstAdministradores.add(dub);
			}
		} 
		catch(Exception e){ System.out.println("Error DAO Administrador (Funcion getAdministradores): " + e.getMessage()); }				
		return lstAdministradores;
	}

		

	
	
	//////////////////////////////////// PROVEEDOR /////////////////////////////////////////////
	
	
	////////////////////////////////////////////////////////////////////////// GUARDAR ////
	

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean guardarProveedor(DataProveedor dataProveedor) throws Exception {		
		boolean resultado = false;
		Proveedor u = new Proveedor(dataProveedor);
		// Persisto el Proveedor
		try{
			em.persist(u);	
			em.flush();
			resultado = true;
		}catch(Exception e){
			System.out.println("Error DAO Proveedor (Funcion guardarProveedor): " + e.getMessage());
		}
		return resultado;
	}

	
	////////////////////////////////////////////////////////////////////////// MODIFICAR ////	


	@Override
	public void modificarProveedor(DataProveedor da) {
		try{
			Proveedor usr = em.find(Proveedor.class, da.getMail());
			
			usr.setNick(da.getNick());
			usr.setNomCompleto(da.getNomCompleto());
			usr.setApellido(da.getApellido());
			usr.setFechaNto(da.getFechaNto());
			usr.setMovil(da.getMovil());
			usr.setSexo(da.getSexo());

			usr.setQr(da.getQr());			
			
			em.persist(usr);		
			em.flush();
		}catch(Exception e){
			System.out.println("Error DAO Proveedor (Funcion modificarProveedor): " + e.getMessage());
		}
	}

	
	////////////////////////////////////////////////////////////////////////// ELIMINAR ////	
	

	@Override
	public void eliminarProveedor(String mail) {
		try{				
			 Proveedor a = em.find(Proveedor.class, mail);		
			 a.setEstado(Estado.INACTIVO.toString());
			 //em.remove(a);
			 em.persist(a);
			 em.flush();
		} catch(Exception e){
			System.out.println("Error DAO Proveedor (Funcion eliminarProveedor): " + e.getMessage());
		}
	}
	
	
	////////////////////////////////////////////////////////////////////////// EXISTE ////
	

	@Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)		
	public boolean existeProveedor(String mail) throws Exception {		
		boolean existe = false;
		try{			
			Query q = em.createQuery("select u from Proveedor u where u.mail = ?1 and u.estado = ?2");
			q.setParameter(1, mail);
			q.setParameter(2, Estado.ACTIVO.toString());			
			if (!q.getSingleResult().equals(null)) existe = true;
			
			//if (!em.find(Proveedor.class, mail).equals(null)) existe = true;
			
		}catch(Exception e){ System.out.println("Error DAO Proveedor (Funcion existeProveedor): " + e.getMessage()); }				
		return existe;
	}
	
	
	////////////////////////////////////////////////////////////////////////// OBTENER ////
	

	@Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)	
	public DataProveedor obtenerProveedor(String mail) throws Exception {
		Usuario u = new Proveedor();
		DataProveedor dub = null;
		try{			
			Query q = em.createQuery("select u from Proveedor u where u.mail = ?1 and u.estado = ?2");
			q.setParameter(1, mail);
			q.setParameter(2, Estado.ACTIVO.toString());			
		    u = (Proveedor) q.getSingleResult();
		    dub = new DataProveedor((Proveedor) u);
		} 
		catch(Exception e){ System.out.println("Error DAO Proveedor (Funcion obtenerProveedor): " + e.getMessage()); }				
		return dub;
	}

	
	////////////////////////////////////////////////////////////////////////// OBTENER TODOS ////
	

	@Override
	public List<DataProveedor> getProveedores() {
		List<DataProveedor> lstProveedores = new ArrayList<DataProveedor>();
		try{		
			Query q = em.createQuery("select u from Proveedor u");
			@SuppressWarnings("unchecked")
			List<Proveedor> lstAdminsDB = (List<Proveedor>) q.getResultList();
			for (Proveedor ub : lstAdminsDB) {
				DataProveedor dub = new DataProveedor(ub);
				lstProveedores.add(dub);
			}
		} 
		catch(Exception e){ System.out.println("Error DAO Proveedor (Funcion getProveedores): " + e.getMessage()); }				
		return lstProveedores;
	}


	
	//////////////////////////////////////////////// CLIENTE ////////////////////////////////////////////////////////
	
	
	

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean guardarCliente(DataCliente cli) throws Exception {
		boolean resultado = false;

		try{
			
		   // Persisto el Usuario	
			Usuario c = cli.dataClienteToUsuario();
			em.persist(c);
			resultado = true;
			
		}catch(Exception e){	
			System.out.println("Error DAO Cliente (Funcion guardarCliente): " + e.getMessage()); }
		
		return resultado;
	}



	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void eliminarCliente(String mail) throws Exception {
	
		try {
			Usuario c = em.find(Usuario.class, mail);
			if (c != null){
		        c.setEstado(Estado.INACTIVO.toString());
			}
			em.persist(c);
			em.flush();
		} catch (Exception e) {
			System.out.println("Error DAO Cliente (Funcion eliminarCliente): " + e.getMessage());
		
		}
	}



	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void modificarCliente(DataCliente nuevosDatos) throws Exception {
		
		try {		
			Cliente c2 = em.find(Cliente.class, nuevosDatos.getMail());
			
			c2.setNick(nuevosDatos.getNick());
	        c2.setNomCompleto(nuevosDatos.getNomCompleto());
	        c2.setApellido(nuevosDatos.getApellido());
	        c2.setMovil(nuevosDatos.getMovil());
	        c2.setSexo(nuevosDatos.getSexo());
	        c2.setFechaNto(nuevosDatos.getFechaNto().toString());
	        
			em.persist(c2);
			em.flush();
		} catch (Exception e) {
			System.out.println("Error DAO Cliente (Funcion modificarCliente): " + e.getMessage());
		}
		
	}

	
	
	@Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
	public List<DataCliente> getListaClientes() throws Exception {	
		
		List<DataCliente> lista_clientes = new ArrayList<DataCliente>();
		try{		
			Query q = em.createQuery("select u from Cliente u where u.estado = ?1");
			
			String estado = "ACTIVO";
			q.setParameter(1, estado);
			
			@SuppressWarnings("unchecked")
			List<Usuario> resultado = (List<Usuario>) q.getResultList();
			if (resultado!=null){
				for(Usuario u : resultado) {
					DataCliente du = new DataCliente();
					du.setMail(u.getMail());
					du.setNomCompleto(u.getNomCompleto());
					du.setPass(u.getPass());
					du.setEstado(Estado.valueOf(u.getEstado()));
					lista_clientes.add(du);
				}
			}
		} 
		catch(Exception e){ System.out.println("Error DAO Cliente (Funcion getListaClientes): " + e.getMessage()); }				
		return lista_clientes;
	}
	

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public DataCliente buscarCliente(String mail) throws Exception {
		DataCliente dc = new DataCliente();
		try {
			Usuario c = em.find(Usuario.class, mail);
			if (c != null){
			DataCliente dcAux = new DataCliente();
			dc =dcAux.usuarioToDataCliente(c);
			
			}

		} catch (Exception e) {
			System.out.println("Error DAO Cliente (Funcion buscarCliente): " + e.getMessage());
		
		}
		return dc;
	}


	@Override
	public boolean existeCliente(String mail) throws Exception {
		boolean ok = false;
		try {			
			Query q = em.createQuery("select u from Cliente u where u.mail = ?1 and u.estado = ?2");
			q.setParameter(1, mail);
			q.setParameter(2, Estado.ACTIVO.toString());
			if (!q.getSingleResult().equals(null)) ok = true;
		} catch (Exception e) {
			System.out.println("Error DAO Cliente (Funcion existeCliente) " + e.getMessage());
		}
		return ok;
	}


	@Override
	public boolean validarLogin(String mail, String pass) throws Exception {
			boolean ok = false;
			Usuario u = null;
		try {
			
			Query q = em.createQuery("select c from Cliente c where c.mail = ?1 and c.pass = ?2");
			q.setParameter(1, mail);
		    q.setParameter(2, pass);			
		    u = (Usuario) q.getSingleResult();
		    if(u != null)
		    	ok= true;
			
		} catch (Exception e) {
			System.out.println("Error DAO Cliente (Funcion validarLogin) " + e.getMessage());
		}
		return ok;
	}
	
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean RegistroClienteACanal(String mail, String idRegistroGCM) throws Exception {
		boolean ok = false;
		
		try {
			 Usuario u = em.find(Usuario.class, mail);
			 Cliente c = (Cliente) u;
			 c.setGcm_regid(idRegistroGCM);
			 em.flush();
			 ok = true;
			
		} catch (Exception e) {
			System.out.println("Error DAO Usuario (Funcion RegistroClienteCanal: " + e.getMessage());
		}

		return ok;
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public String getCodigoClienteAndroid(String mail) throws Exception{
		String cod = null;
		try {
			
			 Usuario u = em.find(Usuario.class, mail);
			 Cliente c = (Cliente) u;
			 if(c.getGcm_regid() != null)
				 cod = c.getGcm_regid();
			 em.flush();
	
			
		} catch (Exception e) {
			System.out.println("Error DAO Usuario Funcion getCodigoClilenteAndroid: " + e.getMessage());
		}
		return cod;	

	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void agregarContenidoDigitalWishlist(String mail, int idContenido) throws Exception{
		
		try {
			ContenidoDigital cd = em.find(ContenidoDigital.class, idContenido);
			Cliente u = em.find(Cliente.class, mail);
			u.getContenidosdigitales().add(cd);			
			em.persist(u);
			em.flush();			
		} catch (Exception e) {
			System.out.println("Error DAO Usuario Funcion agregarContenidoDigitalWishlist: " + e.getMessage());
		}	
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public boolean existeContenidoDigitalWishlist(String mail, int idContenido) throws Exception{
		boolean dev = false;
		try {
			Query q = em.createQuery("SELECT w.contenidosdigitales FROM Cliente w WHERE w.mail = ?1 and ?2 in (select c.idContenido from Cliente.contenidosdigitales c)");
			q.setParameter(1, mail);
			q.setParameter(2, idContenido);
			if (!q.getResultList().equals(null)) dev = true;
		} catch (Exception e) {
			System.out.println("Error DAO Usuario Funcion existeContenidoDigitalWishlist: " + e.getMessage());
		}
		return dev;
	}
	
	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public List<DataContenidoDigital> obtenerWishlist(String mail) throws Exception{
		List<DataContenidoDigital> lst = new ArrayList<DataContenidoDigital>();
		try {
			Cliente c = em.find(Cliente.class, mail);
			List<ContenidoDigital> cds = c.getContenidosdigitales();
			for (ContenidoDigital contenidoDigital : cds) {
				lst.add(new DataContenidoDigital(contenidoDigital));
			}
		} catch (Exception e) {
			System.out.println("Error DAO Usuario Funcion obtenerWishlist: " + e.getMessage());
		}	
		return lst;
	}

	
	
}
